package blog.spring.db.dao.impl;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;

import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateTemplate;

import blog.core.util.DaoUtils;
import blog.spring.db.dao.IBaseDAO;

public abstract class BaseDAO<T> implements IBaseDAO<T> {

	public enum SortType {
		ASC("asc"), DESC("desc");
		private String value;

		private SortType(String value) {
			this.value = value;
		}
	}

	@Resource
	private HibernateTemplate hibernateTemplate;

	private Class entityClass;

	/**
	 * 获取当前线程Session
	 *
	 * @return 当前的Session
	 */
	@Override
	public Session getCurrentSession() {
		hibernateTemplate.getSessionFactory();
		if (hibernateTemplate.getSessionFactory().getCurrentSession() == null)
			return hibernateTemplate.getSessionFactory().openSession();
		else
			return hibernateTemplate.getSessionFactory().getCurrentSession();
	}

	public BaseDAO() {
		/*
		 * 根据反射获取实现类T的类型
		 */
		Type genType = getClass().getGenericSuperclass();
		Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
		entityClass = (Class) params[0];
	}

	@Override
	public void insert(T entity) {
		this.hibernateTemplate.save(entity);
	}

	@Override
	public void delete(T entity) {
		this.hibernateTemplate.delete(entity);

	}

	@Override
	public void update(T entity) {
		this.hibernateTemplate.update(entity);

	}

	@Override
	public T selectById(int id) {
		return (T) this.hibernateTemplate.get(entityClass, id);
	}

	@Override
	public T selectByName(String paramName, String name) {
		Map<String, Object> conditions = new HashMap<>();
		conditions.put(paramName, name);
		return searchUnique(conditions, false);
	}

	@Override
	public boolean selectByNameIsExist(String name) {
		return selectByName(name) != null;
	}

	@Override
	public List<T> selectList(Integer pageNum, Integer pageSize, String name,
			String sort) {
		return searchList(null, pageNum, pageSize, name, sort, true);
	}

	@Override
	public List<T> searchList(Map<String, Object> conditions, Integer pageNum,
			Integer pageSize, String name, String sort, Boolean islike) {
		// 获取基本查询语句
		String hql = DaoUtils.getBasicHql(entityClass);
		return searchListWithTheBasicHql(hql, conditions, pageNum, pageSize,
				name, sort, islike);
	}

	@Override
	public List<T> searchListWithTheBasicHql(String hql,
			Map<String, Object> conditions, Integer pageNum, Integer pageSize,
			String name, String sort, Boolean islike) {

		return getQueryWithTheBasicHql(hql, conditions, pageNum, pageSize,
				name, sort, islike).list();
	}

	@Override
	public Query getQueryWithTheBasicHql(String hql,
			Map<String, Object> conditions, Integer pageNum, Integer pageSize,
			String name, String sort, Boolean islike) {
		Query query = null;
		int[] keys = null;
		Object[] values = null;
		// 是否存在条件
		if (conditions != null && conditions.size() > 0) {
			values = new Object[conditions.size()];
			keys = new int[conditions.size()];
			int i = 0;
			for (Entry<String, Object> param : conditions.entrySet()) {
				String key = param.getKey();
				Object value = param.getValue();
				if (value == null) {
					hql += "and t." + key + " is null ";
					continue;
				} else if (value instanceof String && islike != false)
					hql += "and t." + key + " like ? ";
				else
					hql += "and t." + key + " = ? ";
				values[i] = value;
				keys[i] = i;
				i++;
			}
		}
		if (sort != null) {
			if (name == null && "".equals(name)) {
				System.out.println("排序列名不能为空!");
			}
			hql += " order by t." + name;
			switch (sort) {
			case "asc":
				hql += " asc ";
				break;
			case "desc":
				hql += " desc ";
				break;
			default:
				System.out.println("不明的排序方式!");
			}
		}
		// 创建query对象
		query = getCurrentSession().createQuery(hql);
		if (keys != null) {
			for (int i = 0; i < values.length; i++) {
				if (values[i] == null)
					continue;
				if (values[i] instanceof String && islike != false)
					query = query.setParameter(keys[i], "%" + values[i] + "%");
				else
					query = query.setParameter(keys[i], values[i]);
			}
		}
		// 设置分页
		if (pageNum != null) {
			query.setFirstResult((pageNum - 1) * pageSize);
			query.setMaxResults(pageSize);
		}

		return query;
	}

	@Override
	public List<T> selectAll() {
		return selectList(null, null, null, null);
	}

	@Override
	public T searchUnique(Map<String, Object> conditions, Boolean islike) {
		List<T> list = searchList(conditions, null, null, null, null, islike);
		return list == null ? null : list.size() > 0 ? list.get(0) : null;
	}

	@Override
	public abstract T selectByName(String name);

	@Override
	public int selectAllCount() {
		return searchCount(null);
	}

	@Override
	public int searchCount(Map<String, Object> conditions) {
		return ((Number) getQueryWithTheBasicHql(
				"select count(*) from " + DaoUtils.getClassStr(entityClass),
				conditions, null, null, null, null, null).uniqueResult())
				.intValue();
	}
}
